package com.uottawa.library.service;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.uottawa.library.dao.LoanDAO;
import com.uottawa.library.dao.UserDAO;
import com.uottawa.library.domain.Item;
import com.uottawa.library.domain.Loan;
import com.uottawa.library.domain.LoanPeriod;
import com.uottawa.library.domain.User;

public class LoanService {
	
	private LoanDAO loanDao = new LoanDAO();
	private UserDAO userDao = new UserDAO();
	private LoanPeriodService loanPeriodSerice = new LoanPeriodService();

	
	public String borrowLoanCopy(Item item, User user) {
		userDao.updateUserBalance();
		double balance = userDao.getUserBalance(user.getUserId());
		Loan loan = loanDao.getLoanByItemId(item.getItemId());
		
		boolean itemIsBorrowed = false; // if the item in the loan, it is borrowed
		if(loan != null && !loan.isReturned() ) {
			itemIsBorrowed = true;
		}
		if(balance > 0 ) {
			return "rejected ! you have an outstanding balance";
		}
		if(itemIsBorrowed) {
			return "rejected! item is already borrowed";
		}
		LoanPeriodService loanPeriodService = new LoanPeriodService();
		LoanPeriod loanPeriod = loanPeriodService.getLoanPeriod(1);
		
		Date currentDate = new Date(); // current date of now 
		Timestamp expDate =updateTimestamp( new Timestamp(currentDate.getTime()),0,0,0,loanPeriod.getDuration(),0);
		// create a new loan 
		loan = new Loan();
		loan.setExpiryDate(expDate);
		loan.setExtensions(0);
		loan.setUserId(user.getUserId());
		loan.setItemId(item.getItemId());
		
		loanDao.addLoan(loan);
		return "success";
	} 

	
	private Timestamp updateTimestamp(Timestamp timestamp,int months,int days,int hours, int minutes, int seconds)
	{
		if(months > 0)
			timestamp.setMonth(timestamp.getMonth()+months);
		if(days > 0)
			timestamp.setDate(timestamp.getDay()+days);
		if(hours >0 )
			timestamp.setHours(timestamp.getHours() +hours);
		if(minutes > 0)
			timestamp.setMinutes(timestamp.getMinutes() + minutes);	
		if(seconds >0)
			timestamp.setSeconds(timestamp.getSeconds()+seconds);
		
		return timestamp;
		
	}

	public String renewLoan(int loanId, User user) {
		userDao.updateUserBalance();
		Loan loan = this.getLoan(loanId);
		if(user.getUserId() == loan.getUserId())
		{
			LoanPeriodService loanPeriodService = new LoanPeriodService();
			int maxRenewals = loanPeriodService.getMaxRenewals();
			Date currentDate = Calendar.getInstance().getTime(); // current date of now 
			
			if (userDao.getUserBalance(user.getUserId()) == 0) // no outstanding balance 
			{
				boolean expiryDateNotPassed = loan.getExpiryDate().after(currentDate);
				boolean loanNotExceedMaxRewals = loan.getExtensions() < maxRenewals;
				if(loanNotExceedMaxRewals && expiryDateNotPassed)
					
				{
					LoanPeriod loanPeriod = loanPeriodService.getLoanPeriod(loan.getLoanPriodId());
					int renewalPeriodAsMinutes= loanPeriod.getDuration();
				
					Timestamp updatedExpiryDate = updateTimestamp(loan.getExpiryDate(),0,0,0,renewalPeriodAsMinutes,0);
					loan.setExpiryDate(updatedExpiryDate);
					loan.setExtensions(loan.getExtensions()+1);
					loan.setLoanPriodId(loan.getLoanPriodId()+1);

					
					return (loanDao.updateLoan(loan))? "Your loan has been extended":"unable to update the loan ...";
					
					
				}
				
			}
			else 
				return "You have outstanding balance in your account ...";
			
		

			
			
		}
		return "You are not allowed to renew this loan ...";		
	}

	public Loan getLoan(int loanId) {
	
		return loanDao.getLoan(loanId);
	}
	
	public String returnLoan(Loan loan){
		userDao.updateUserBalance();
		User user = userDao.getUser(loan.getUserId());
		
		if(checkNotification(user)){
		boolean returned = loanDao.returnLoan(loan);
	
			if(returned){
				return "success";
			}
			else{
				return "rejected";
			}
		}
		
		else{
			return "rejected";
		}
	}

	public int getNumberOfExtenstions(Loan loan) {
		return loanDao.NumberOfExtenstions(loan);
	}

	/**
	 * This function simply finds out if a user has AT LEAST 1 expired loan 
	 * In that case once the user logs in this function will be executed and if
	 * user has an expired loan than a pop up will appear
	 * @param user
	 * @return
	 */
	public Boolean checkNotification(User user){
		userDao.updateUserBalance();
		if (userDao.getUserBalance(user.getUserId()) > 0){
			return false;
		}
		return true;
	}


	public List<Loan> getLoansWithFeesForUser(int userId) {
		return loanDao.getLoansWithFeesForUser(userId);
	}

	public void chargeFees(int userId, int itemId, double fees ) {
		loanDao.chargeFees(userId, itemId, fees);
	}
	
	public String payFees(int loanId) {
		Loan loan = loanDao.getLoan(loanId);
		if(!loan.isReturned()) {
			return "failed! Please return the item first";
		}
		boolean paid = loanDao.payFees(loanId);
		String result = (paid) ? "success" : "failed";
		return result;
	}


	public List<Loan> getAllLoan() {
		
		return loanDao.getAllLoan();
	}


	public List<Loan> getAllUserExtendableLoan(int userId) {
		return loanDao.getAllUserExtendableLoan(userId,loanPeriodSerice.getMaxRenewals());
	}


	public List<Loan> getAllUserLoan(int userId) {
		return loanDao.getAllUserLLoan(userId);
	}
	
	public String updateLoan(Loan loan){
		Boolean result = loanDao.updateLoan(loan);
		if(result){
			return "succesful";
		}
		else{
			return "rejected";
		}
	}

}
